//    Copyright (C) Kherty.  All rights reserved.
using System;
using System.ComponentModel;
using System.Diagnostics.Contracts;
using System.Reflection;
using OpenLS.Core;
using OpenLS.Core.Serialization;
using OpenLS.Spreadsheet.Serialization;

namespace OpenLS.Spreadsheet
{
    ///<summary>
    /// Represents the page setup of a sheet
    ///</summary>
    public class PageSetup : IOfficeXmlSerializable, INotifyPropertyChanged
    {
        private bool _blackAndWhite;
        private CellComments _cellComments = CellComments.None;
        private int _copies = 1;
        private bool _draft;
        private PrintError _errors = PrintError.Displayed;
        private int _firstPageNumber = 1;
        private int _fitToHeight = 1;
        private int _fitToWidth = 1;
        private int _horizontalDpi = 600;
        private Orientation _orientation = Orientation.Default;
        private PageOrder _pageOrder = PageOrder.DownThenOver;
        private PaperSize _paperSize = PaperSize.Letter;
        private int _scale = 100;
        private bool _useFirstPageNumber;
        private bool _usePrinterDefault = true;
        private int _verticalDpi = 600;
        private byte[] data;

        public int FirstPageNumber
        {
            get { return _firstPageNumber; }
            set
            {
                checkPositiveValue(value);
                _firstPageNumber = value;
                notifyPropertyChanged("FirstPageNumber");
            }
        }

        public int FitToWidth
        {
            get { return _fitToWidth; }
            set
            {
                checkPositiveValue(value);
                _fitToWidth = value;
                notifyPropertyChanged("FitToWidth");
            }
        }

        public int FitToHeight
        {
            get { return _fitToHeight; }
            set
            {
                checkPositiveValue(value);
                _fitToHeight = value;
                notifyPropertyChanged("FitToHeight");
            }
        }

        public PageOrder PageOrder
        {
            get { return _pageOrder; }
            set
            {
                _pageOrder = value;
                notifyPropertyChanged("PageOrder");
            }
        }

        public Orientation Orientation
        {
            get { return _orientation; }
            set
            {
                _orientation = value;
                notifyPropertyChanged("Orientation");
            }
        }

        public bool UsePrinterDefault
        {
            get { return _usePrinterDefault; }
            set
            {
                _usePrinterDefault = value;
                notifyPropertyChanged("UsePrinterDefault");
            }
        }

        public bool BlackAndWhite
        {
            get { return _blackAndWhite; }
            set
            {
                _blackAndWhite = value;
                notifyPropertyChanged("BlackAndWhite");
            }
        }

        public int Scale
        {
            get { return _scale; }
            set
            {
                if (value < 10 || value > 400)
                    throw new ArgumentException("value");
                _scale = value;
                notifyPropertyChanged("Scale");
            }
        }

        public int HorizontalDpi
        {
            get { return _horizontalDpi; }
            set
            {
                checkPositiveValue(value);
                _horizontalDpi = value;
                notifyPropertyChanged("HorizontalDpi");
            }
        }

        public bool Draft
        {
            get { return _draft; }
            set
            {
                _draft = value;
                notifyPropertyChanged("Draft");
            }
        }

        public CellComments CellComments
        {
            get { return _cellComments; }
            set
            {
                _cellComments = value;
                notifyPropertyChanged("CellComments");
            }
        }

        public bool UseFirstPageNumber
        {
            get { return _useFirstPageNumber; }
            set
            {
                _useFirstPageNumber = value;
                notifyPropertyChanged("UseFirstPageNumber");
            }
        }

        public PrintError Errors
        {
            get { return _errors; }
            set
            {
                _errors = value;
                notifyPropertyChanged("Errors");
            }
        }

        public int VerticalDpi
        {
            get { return _verticalDpi; }
            set
            {
                checkPositiveValue(value);
                _verticalDpi = value;
                notifyPropertyChanged("VerticalDpi");
            }
        }

        public int Copies
        {
            get { return _copies; }
            set
            {
                checkPositiveValue(value);
                _copies = value;
                notifyPropertyChanged("Copies");
            }
        }

        public PaperSize PaperSize
        {
            get { return _paperSize; }
            set
            {
                _paperSize = value;
                notifyPropertyChanged("PaperSize");
            }
        }

        #region INotifyPropertyChanged Members

        public event PropertyChangedEventHandler PropertyChanged;

        #endregion

        #region IOfficeXmlSerializable Members

        void IOfficeXmlSerializable.ReadXml(ReadContext context)
        {
            using (ReadContext c = context.Read("pageSetup"))
            {
                var rid = c.GetOptionalString(OfficeConstants.RelationshipNamespace + "id");
                if (rid != null)
                {
                    using (var stream = c.OpenRelatedStream(rid))
                    {
                        data = new byte[stream.Length];
                        stream.Read(data, 0, data.Length);
                    }
                } _paperSize = (PaperSize)c.GetOptionalInteger("paperSize", 1);
                _firstPageNumber = c.GetOptionalUIntegerAsInteger("firstPageNumber", 1);
                _fitToWidth = c.GetOptionalInteger("fitToWidth", 1);
                _fitToHeight = c.GetOptionalInteger("fitToHeight", 1);
                _pageOrder = c.GetOptionalEnum("pageOrder", PageOrder.DownThenOver);
                _orientation = c.GetOptionalEnum("orientation", Orientation.Default);
                _usePrinterDefault = c.GetOptionalBoolean("usePrinterDefault", true);
                _blackAndWhite = c.GetOptionalBoolean("blackAndWhite", false);
                _scale = c.GetOptionalInteger("scale", 100);
                _horizontalDpi = Math.Max(c.GetOptionalUIntegerAsInteger("horizontalDpi", 600), 0);
                _draft = c.GetOptionalBoolean("draft", false);
                _cellComments = c.GetOptionalEnum("cellComments", CellComments.None);
                _useFirstPageNumber = c.GetOptionalBoolean("useFirstPageNumber", false);
                _errors = c.GetOptionalEnum("errors", PrintError.Displayed);
                _verticalDpi = Math.Max(c.GetOptionalUIntegerAsInteger("verticalDpi", 600), 0);
                _copies = c.GetOptionalInteger("copies", 1);
            }
        }

        void IOfficeXmlSerializable.WriteXml(WriteContext context)
        {
            using (WriteContext c = context.Write("pageSetup"))
            {
                if (data != null)
                {
                    string rid;
                    using (
                        var stream = c.CreateRelatedStream("printerSetting{0}.bin",
                                                           SpreadsheetConstants.PrinterSettingsContentType,
                                                           SpreadsheetConstants.PrinterSettings, out rid))
                    {
                        stream.Write(data, 0, data.Length);
                        c.SetString(OfficeConstants.RelationshipNamespace + "id", rid);
                    }
                }
                c.SetOptionalInteger("paperSize", (int) _paperSize, 1);
                c.SetOptionalUIntegerAsInteger("firstPageNumber", _firstPageNumber, 1);
                c.SetOptionalInteger("fitToWidth", _fitToWidth, 1);
                c.SetOptionalInteger("fitToHeight", _fitToHeight, 1);
                c.SetOptionalEnum("pageOrder", _pageOrder, PageOrder.DownThenOver);
                c.SetOptionalEnum("orientation", _orientation, Orientation.Default);
                c.SetOptionalBoolean("usePrinterDefault", _usePrinterDefault, true);
                c.SetOptionalBoolean("blackAndWhite", _blackAndWhite, false);
                c.SetOptionalInteger("scale", _scale, 100);
                c.SetOptionalInteger("horizontalDpi", _horizontalDpi, 600);
                c.SetOptionalBoolean("draft", _draft = false);
                c.SetOptionalEnum("cellComments", _cellComments, CellComments.None);
                c.SetOptionalBoolean("useFirstPageNumber", _useFirstPageNumber, false);
                c.SetOptionalEnum("errors", _errors, PrintError.Displayed);
                c.SetOptionalInteger("verticalDpi", _verticalDpi, 600);
                c.SetOptionalInteger("copies", _copies, 1);
            }
        }

        #endregion

        private static void checkPositiveValue(int value)
        {
            if (value < 0) throw new ArgumentException("value");
        }

        private void notifyPropertyChanged(string propertyName)
        {
            Contract.Requires(
                GetType().GetProperty(propertyName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) !=
                null);
            if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}